﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
//using System.Threading.Tasks;
using Net_framework_4.System;
using UnityEngine;
namespace VoxelBlock
{
    public interface IReadVoxelDictionary<TKey, TValue>
    {
        TValue this[TKey key] { get; set; }
        TValue this[int key] { get; set; }
        bool TryGetValue(TKey key, out TValue value);
        bool ContainsKey(TKey key);
        void Clear();
        IEnumerable<TValue> Values { get; }
    }

}
namespace VoxelBlock.VoxelBlock3D
{
    public struct UpdateShadowUnitData
    {
        public int direction; 
        public int chunkID;
        public int chunkIndex;
        public ByteTo8Bool shadow;
        public UpdateShadowUnitData(int direction, int chunkID, int chunkIndex , ByteTo8Bool shadow)
        {
            this.direction = direction;
            this.chunkID = chunkID;
            this.chunkIndex = chunkIndex;
            this.shadow = shadow;
        }
        public UpdateShadowUnitData(int direction,Voxel3D voxel)
        {
            this.direction = direction;
            this.chunkID = voxel.chunkKey;
            this.chunkIndex = voxel.chunkIndex;
            this.shadow = voxel.colorShadows[direction];
        }
    }

    internal class ChunkDictionary : IReadVoxelDictionary<int, VoxelChunk>
    {
        VoxelChunk[] allVoxelChunk = new VoxelChunk[16 * 16 * 16];
        public VoxelChunk this[int key]
        {
            get
            {
                return allVoxelChunk[key];
            }

            set
            {
                allVoxelChunk[key] = value;
            }
        }

        public IEnumerable<VoxelChunk> Values
        {
            get
            {
                for (int i = 0; i < 4096; i++)
                {
                    if (allVoxelChunk[i] != null)
                    {
                        yield return allVoxelChunk[i];
                    }
                }
            }
        }
        public void Clear()
        {
            allVoxelChunk = new VoxelChunk[16 * 16 * 16];
        }

        public bool ContainsKey(int key)
        {
            if (allVoxelChunk[key] == null)
            {
                return false;
            }
            return true;
        }

        public bool TryGetValue(int key, out VoxelChunk value)
        {
            value = allVoxelChunk[key];
            if (value == null)
            {
                return false;
            }
            return true;
        }
    }


    public class MyDictionary : IReadVoxelDictionary<Vector3Int, Voxel3D>
    {
        //TValue this[TKey key] { get; set; }
        //ICollection<TKey> Keys { get; }
        //ICollection<TValue> Values { get; }
        //bool ContainsKey(TKey key);
        //bool Remove(TKey key);
        //bool TryGetValue(TKey key, out TValue value);

        Voxel3D[] allVoxel = new Voxel3D[256 * 256 * 256];

        public void Clear()
        {
            allVoxel = new Voxel3D[256 * 256 * 256];
        }

        public MyDictionary(object dictionaryVoxelChunks)
        {
            this.dictionaryVoxelChunks = dictionaryVoxelChunks as IReadVoxelDictionary<int, VoxelChunk>;
        }
        internal IReadVoxelDictionary<int, VoxelChunk> dictionaryVoxelChunks;


        private int GetPositionIndex(Vector3Int point)
        {
            return (point.x + 128) + ((point.y + 1) << 8) + ((point.z + 128) << 16);
        }

        public Voxel3D this[int index]
        {
            get
            {
                return allVoxel[index];
            }
            set
            {
                allVoxel[index] = value;
            }
        }

        public Voxel3D this[Vector3Int point]
        {
            get
            {
                return allVoxel[GetPositionIndex(point)];
            }
            set
            {
                allVoxel[GetPositionIndex(point)] = value;
            }
        }

        public bool ContainsKey(Vector3Int point)
        {
            int index = GetPositionIndex(point);
            if (0 <= index && index < allVoxel.Length)
            {
                Voxel3D voxel = allVoxel[index];
                if (voxel == null)
                {
                    return false;
                }
            }
            return true;
        }

        private Voxel3D GetVoxel3D(Vector3Int point)
        {
            int chunkX = point.x >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int chunkY = point.y >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int chunkZ = point.z >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int key = (chunkX + 512) + ((chunkY + 512) << 0x0A) + (chunkZ << 0x14);

            int localX = point.x & VoxelCategories.CHUNK_UNIT_LENGTH_Minus1;
            int localY = point.y & VoxelCategories.CHUNK_UNIT_LENGTH_Minus1;
            int localZ = point.z & VoxelCategories.CHUNK_UNIT_LENGTH_Minus1;
            int localKey = localX + (localY << 4) + (localZ << 8);
            VoxelChunk chunk;
            if (dictionaryVoxelChunks.TryGetValue(key, out chunk))
            {
                return chunk.mainVoxels[localKey];
            }
            return null;
        }
        public bool TryGetValue(Vector3Int point, out Voxel3D voxel)
        {
            voxel = allVoxel[GetPositionIndex(point)];
            if (voxel == null)
            {
                return false;
            }
            return true;
        }

        public IEnumerable<Voxel3D> Values
        {
            get
            {
                foreach (VoxelChunk item in dictionaryVoxelChunks.Values)
                {
                    foreach (var item2 in item.mainVoxels)
                    {
                        if (item2 != null)
                        {
                            yield return item2;
                        }
                    }
                }
            }
        }
    }
    /// <summary>
    /// 对应游戏实体的Chunk
    /// </summary>
    internal sealed class EntityChunk
    {
        internal EntityChunk(Vector3Int localPosition, Material material, Transform parent)
        {
            this.localPosition = localPosition * VoxelCategories.CHUNK_UNIT_LENGTH;
            gameObject = new GameObject(localPosition.ToString());
            gameObject.transform.SetParent(parent);

            gameObject.layer = VoxelCategories.CHUNK_GAMEOBJECT_LAYER;
            gameObject.transform.localPosition = this.localPosition;

            meshRenderer = gameObject.AddComponent<MeshRenderer>();
            meshCollider = gameObject.AddComponent<MeshCollider>();
            meshFilter = gameObject.AddComponent<MeshFilter>();
            meshFilter.sharedMesh = new Mesh();
            meshRenderer.material = material;

        }
        internal void UpdateCollider()
        {
            //meshCollider.convex = true; 
            //meshCollider.inflateMesh = true; 
            meshCollider.sharedMesh = meshFilter.sharedMesh;
        }
        internal void RecalculateNormals()
        {
            meshFilter.sharedMesh.RecalculateNormals();
        }


        internal void UpdateUV3(Vector2[] uvs)
        {
            Mesh fmesh = meshFilter.sharedMesh;
            fmesh.uv3 = uvs;
        }

        internal void UpdateUV3(Color[] colors)
        {
            Mesh fmesh = meshFilter.sharedMesh;
            fmesh.colors = colors;
        }

        internal void Update(MyMesh mesh)
        {
            Mesh fmesh = meshFilter.sharedMesh;
            if (mesh.vertices.Length <= 0)
            {
                gameObject.SetActive(false);
                return;
            }
            else
            {
                gameObject.SetActive(true);
            }
            fmesh.Clear();
            fmesh.vertices = mesh.vertices;
            fmesh.uv = mesh.uv;
            fmesh.triangles = mesh.triangles;
            fmesh.uv2 = mesh.uv2; 
            fmesh.uv3 = mesh.uv3; 
            fmesh.colors = mesh.colors;
            fmesh.RecalculateNormals();

            //meshFilter.mesh = fmesh;
            //meshCollider.sharedMesh = mesh;
        }
        internal void Clear()
        {
            //meshFilter.mesh = null;
            //meshCollider.sharedMesh = null;
            GameObject.Destroy(gameObject);
        }


        GameObject gameObject;
        Vector3 localPosition;
        MeshRenderer meshRenderer;
        MeshCollider meshCollider;
        MeshFilter meshFilter;
    }

    /// <summary>
    /// 这个类用来存储更新Chunk时，使用的数据
    /// </summary>
    internal sealed class VoxelChunkSurfaceUpdateDatas
    {
        internal List<int>[] addIndexs;
        internal List<int>[] removeIndexs;

        internal void Clear()
        {
            for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
            {
                addIndexs[i].Clear();
            }
            for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
            {
                removeIndexs[i].Clear();
            }
        }

        internal VoxelChunkSurfaceUpdateDatas()
        {
            addIndexs = new List<int>[VoxelCategories.SURFACE_LENGTH] { new List<int>(), new List<int>(), new List<int>(), new List<int>(), new List<int>(), new List<int>() };
            removeIndexs = new List<int>[VoxelCategories.SURFACE_LENGTH] { new List<int>(), new List<int>(), new List<int>(), new List<int>(), new List<int>(), new List<int>() };
        }
    }

    /// <summary>
    /// Chunk类，它负责一个Chunk的MyMesh数据
    /// </summary>
    internal sealed class VoxelChunk
    {
        /// <summary>
        /// 是否已经完成写入
        /// </summary>
        internal bool isWrite = false;

        //internal Dictionary<int, VoxelChunk> parentDictionaryVoxelChunks;


        private VoxelChunkSurfaceUpdateDatas surfaceUpdateDatas = new VoxelChunkSurfaceUpdateDatas();

        internal VoxelChunkSurfaceUpdateDatas SurfaceUpdateDatas
        {
            get { return surfaceUpdateDatas; }
        }

        private VoxelChunkSurface[] mainVoxelChunkSurfaces = new VoxelChunkSurface[VoxelCategories.SURFACE_LENGTH]
             {
                 new VoxelChunkSurface(VoxelDirection.Right),new VoxelChunkSurface(VoxelDirection.Left),new VoxelChunkSurface(VoxelDirection.Up),
                 new VoxelChunkSurface(VoxelDirection.Down),new VoxelChunkSurface(VoxelDirection.Front),new VoxelChunkSurface(VoxelDirection.Break)
             };

        internal Voxel3D[] mainVoxels = new Voxel3D[VoxelCategories.CHUNK_LENGTH];
        internal List<Voxel3D> tempVoxels = new List<Voxel3D>(1024);


        internal int m_Id = 0;
        internal Vector3Int chunkPosition;

        public readonly int Key = 0;

        public override int GetHashCode()
        {
            return Key;
        }

        internal VoxelChunk(Vector3Int position)
        {
            this.chunkPosition = position;
            Key = (position.x + 8) + (position.y) * 16 + (position.z + 8) * 256;
        }
        internal VoxelChunk(int a_x, int a_y, int a_z)
        {
            chunkPosition = new Vector3Int(a_x, a_y, a_z);
        }

        internal void UpdateUV(int direction, int chunkIndex, int uvKey)
        {
            mainVoxelChunkSurfaces[direction].UpdateUV(chunkIndex, uvKey);
        }

        internal void UpdateColors(int direction, int chunkIndex, int uvKey)
        {
            mainVoxelChunkSurfaces[direction].UpdateColors(chunkIndex, uvKey);
        }

        internal void UpdateShadowColors(int direction, int chunkIndex, ByteTo8Bool colorShadows)
        {
            mainVoxelChunkSurfaces[direction].UpdateShadowUV3(chunkIndex, colorShadows);
        }



        internal void Update(int direction)
        {
            mainVoxelChunkSurfaces[direction].Update(surfaceUpdateDatas, mainVoxels);
        }

        internal MyMesh overMyMesh;
        internal MyMesh GetMyMesh()
        {
            MyMesh myMesh = new MyMesh();
            myMesh.vertices = ArrayTranscriptionAlgorithm.MergeArray<Vector3>(
                mainVoxelChunkSurfaces[0].vertices,
                mainVoxelChunkSurfaces[1].vertices,
                mainVoxelChunkSurfaces[2].vertices,
                mainVoxelChunkSurfaces[3].vertices,
                mainVoxelChunkSurfaces[4].vertices,
                mainVoxelChunkSurfaces[5].vertices
                );
            myMesh.uv = ArrayTranscriptionAlgorithm.MergeArray<Vector2>(
                mainVoxelChunkSurfaces[0].uv,
                mainVoxelChunkSurfaces[1].uv,
                mainVoxelChunkSurfaces[2].uv,
                mainVoxelChunkSurfaces[3].uv,
                mainVoxelChunkSurfaces[4].uv,
                mainVoxelChunkSurfaces[5].uv
                );
            myMesh.uv3 = ArrayTranscriptionAlgorithm.MergeArray<Vector2>(
                mainVoxelChunkSurfaces[0].uv3,
                mainVoxelChunkSurfaces[1].uv3,
                mainVoxelChunkSurfaces[2].uv3,
                mainVoxelChunkSurfaces[3].uv3,
                mainVoxelChunkSurfaces[4].uv3,
                mainVoxelChunkSurfaces[5].uv3
                );
            myMesh.colors = ArrayTranscriptionAlgorithm.MergeArray<Color>(
                mainVoxelChunkSurfaces[0].colors,
                mainVoxelChunkSurfaces[1].colors,
                mainVoxelChunkSurfaces[2].colors,
                mainVoxelChunkSurfaces[3].colors,
                mainVoxelChunkSurfaces[4].colors,
                mainVoxelChunkSurfaces[5].colors
                );
            myMesh.uv2 = VoxelMetadata3D.Instance.GetUV2(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
            overMyMesh = myMesh;
            return myMesh;
        }

        internal MyMesh GetUVMyMesh()
        {
            overMyMesh.uv = ArrayTranscriptionAlgorithm.MergeArray<Vector2>(
              mainVoxelChunkSurfaces[0].uv,
              mainVoxelChunkSurfaces[1].uv,
              mainVoxelChunkSurfaces[2].uv,
              mainVoxelChunkSurfaces[3].uv,
              mainVoxelChunkSurfaces[4].uv,
              mainVoxelChunkSurfaces[5].uv
              );
            return overMyMesh;
        }
        internal MyMesh GetUV3()
        {
            overMyMesh.uv3 = ArrayTranscriptionAlgorithm.MergeArray<Vector2>(
              mainVoxelChunkSurfaces[0].uv3,
              mainVoxelChunkSurfaces[1].uv3,
              mainVoxelChunkSurfaces[2].uv3,
              mainVoxelChunkSurfaces[3].uv3,
              mainVoxelChunkSurfaces[4].uv3,
              mainVoxelChunkSurfaces[5].uv3
              );
            return overMyMesh;
        }
        internal MyMesh GetColorsMyMesh()
        {
            overMyMesh.colors = ArrayTranscriptionAlgorithm.MergeArray<Color>(
              mainVoxelChunkSurfaces[0].colors,
              mainVoxelChunkSurfaces[1].colors,
              mainVoxelChunkSurfaces[2].colors,
              mainVoxelChunkSurfaces[3].colors,
              mainVoxelChunkSurfaces[4].colors,
              mainVoxelChunkSurfaces[5].colors
              );
            return overMyMesh;
        }


        /// <summary>
        /// 表面
        /// </summary>
        private class VoxelChunkSurface
        {
            internal VoxelChunkSurface(VoxelDirection direction)
            {
                chunk = new int[VoxelCategories.CHUNK_LENGTH];
                for (int x = 0; x < VoxelCategories.CHUNK_LENGTH; x++)
                {
                    chunk[x] = -1;
                }
                this.direction = direction;
                this._direction = (int)direction;
            }

            internal void Update(VoxelChunkSurfaceUpdateDatas voxelChunkSurfaceUpdateDatas, Voxel3D[] voxels)
            {
                ArrayTranscriptionAlgorithm.TranscriptionBolcksArray(
                    _direction,
                     chunk, ref verticesIndex,
                    voxelChunkSurfaceUpdateDatas.addIndexs[_direction], voxelChunkSurfaceUpdateDatas.removeIndexs[_direction]
                    , ref vertices, ref uv, ref uv3, ref colors
                    , voxels
                    );
            }

            internal void UpdateUV(int chunkIndex, int uvKey)
            {
                Array.Copy(VoxelMetadata3D.Instance.allDataUVs, uvKey * VoxelCategories.UNIT_VERTICES_LENGTH, uv, chunk[chunkIndex] * VoxelCategories.UNIT_VERTICES_LENGTH, VoxelCategories.UNIT_VERTICES_LENGTH);
            }

            internal void UpdateColors(int chunkIndex, int uvKey)
            {
                int index = chunk[chunkIndex] * VoxelCategories.UNIT_VERTICES_LENGTH;
                float a = uvKey / 255f;
                colors[index].a = a;
                colors[index + 1].a = a;
                colors[index + 2].a = a;
                colors[index + 3].a = a;
            }

            //internal void UpdateShadowColors(int chunkIndex, ByteTo8Bool colorShadows)
            //{
            //    int index = chunk[chunkIndex] * VoxelCategories.UNIT_VERTICES_LENGTH;
            //    BasicAlgorithm.SetShadowColor(colorShadows, colors, index, VoxelMetadata3D.Instance.allDataColors[_direction]);
            //}

            internal void UpdateShadowUV3(int chunkIndex, ByteTo8Bool colorShadows)
            {
                if (chunk[chunkIndex] > 0)
                {
                    int index = chunk[chunkIndex] * VoxelCategories.UNIT_VERTICES_LENGTH;
                    BasicAlgorithm.SetShadowUV3(colorShadows, uv3, index);
                }
            }

            

            internal int[] chunk;
            internal int[] verticesIndex = new int[0];
            internal Vector3[] vertices = new Vector3[0];
            internal Vector2[] uv = new Vector2[0];
            internal Vector2[] uv3 = new Vector2[0];
            //internal Vector2[] uv2 = new Vector2[0];
            public Color[] colors = new Color[0];

            internal VoxelDirection direction;
            private int _direction;
        }



    }

    /// <summary>
    /// 创建一个绘制核心，它需要一个材质球作为绘制材质
    /// </summary>
    public class DrawVoxel3DCore
    {
        Transform mainTransform;

        /// <summary>
        /// 模型的父节点
        /// </summary>
        public Transform RootTransform
        {
            get
            {
                return mainTransform;
            }
        }

        /// <summary>
        /// 当添加的世界坐标不符合规范时会被忽略，这个函数控制着这个规范
        /// </summary>
        public Func<Vector3Int, bool> AddBlockIsContinue = (worldPosition) => { return false; };


        public void Clear()
        {
            IEnumerable<Vector3Int> scoreQuery =
           from score in allVoxels.Values
           select score.worldPosition;
            //List<Vector3Int>
            //foreach (var item in allVoxels.Values)
            //{

            //}
            DrawRemoveBlock(scoreQuery);
            return;
            foreach (var item in mainGameObjectChunks.Values)
            {
                item.Clear();
            }

            mainGameObjectChunks.Clear();
            allVoxels = new MyDictionary(mainDictionaryVoxelChunks);
            mainDictionaryVoxelChunks.Clear();
            tempGameObjectChunks.Clear();
            //allSelectVoxel.Clear();
        }

        public DrawVoxel3DCore(Material mainMaterial, string name)
        {
            this.mainMaterial = mainMaterial;
            this.allVoxels = new MyDictionary(mainDictionaryVoxelChunks);
            GameObject obj = new GameObject();
            obj.name = name;
            mainTransform = obj.transform;
        }

        public DrawVoxel3DCore(Material mainMaterial, GameObject obj)
        {
            this.mainMaterial = mainMaterial;
            this.allVoxels = new MyDictionary(mainDictionaryVoxelChunks);
            mainTransform = obj.transform;
        }

        public Material mainMaterial;

        //VoxelMetadata3D m_VoxelMetadata3D = new VoxelMetadata3D();
        VoxelMetadata3D m_VoxelMetadata3D = VoxelMetadata3D.Instance;
        //  public Dictionary<Vector3Int, Voxel3D> allVoxels = new Dictionary<Vector3Int, Voxel3D>();
        public MyDictionary allVoxels;
        //public Dictionary<int, Vector3Int> allSelectVoxel = new Dictionary<int, Vector3Int>();


        IReadVoxelDictionary<int, VoxelChunk> mainDictionaryVoxelChunks = new ChunkDictionary();
        Dictionary<int, EntityChunk> mainGameObjectChunks = new Dictionary<int, EntityChunk>();
        Dictionary<int, EntityChunk> tempGameObjectChunks = new Dictionary<int, EntityChunk>();

        /// <summary>
        /// 绘制结束时调用
        /// </summary>
        public void DrawOver()
        {
            foreach (var item in tempGameObjectChunks)
            {
                item.Value.RecalculateNormals();
                item.Value.UpdateCollider();
            }
            tempGameObjectChunks.Clear();
        }

        public void RecalculateNormalsAndUpdateCollider()
        {
            foreach (var item in tempGameObjectChunks)
            {
                item.Value.RecalculateNormals();
                item.Value.UpdateCollider();
            }
            tempGameObjectChunks.Clear();
        }

        public void DrawAddBlock(IEnumerable<SimpleVoxel> blocks)
        {
            HashSet<VoxelChunk> updateVoxelChunks = AddBlocks(blocks);
            if (updateVoxelChunks.Count == 0)
            {
                return;
            }
            foreach (var item in updateVoxelChunks)
            {
                item.GetMyMesh();
            }

            foreach (var item in updateVoxelChunks)
            {
                if (item.isWrite)
                {

                }
                else
                {
                    mainGameObjectChunks[item.Key] = new EntityChunk(item.chunkPosition, mainMaterial, mainTransform);
                    item.isWrite = true;
                }
                tempGameObjectChunks[item.Key] = mainGameObjectChunks[item.Key];
                MyMesh myMesh = item.overMyMesh;
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
                mainGameObjectChunks[item.Key].Update(myMesh);
            }
        }

        public SimpleVoxel[] DrawAddBlock(IEnumerable<Voxel3D> blocks)
        {
            var data1 = AddBlocks(blocks);
            if (data1.Item1 == false)
            {
                return new SimpleVoxel[0];
            }
            HashSet<VoxelChunk> updateVoxelChunks = data1.Item2;

            foreach (var item in updateVoxelChunks)
            {
                item.GetMyMesh();
            }

            foreach (var item in updateVoxelChunks)
            {
                if (item.isWrite)
                {

                }
                else
                {
                    mainGameObjectChunks[item.Key] = new EntityChunk(item.chunkPosition, mainMaterial, mainTransform);
                    item.isWrite = true;
                }
                if (!tempGameObjectChunks.ContainsKey(item.Key))
                {
                    tempGameObjectChunks[item.Key] = mainGameObjectChunks[item.Key];
                }

                MyMesh myMesh = item.overMyMesh;
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);

                //chunkMesh.RecalculateNormals();
                mainGameObjectChunks[item.Key].Update(myMesh);
            }
            return data1.Item3;
        }

        public List<SimpleVoxel> DrawRemoveBlock(IEnumerable<Vector3Int> positions)
        {
            var data1 = RemoveBlocks(positions);
            if (data1.Item1 == false)
            {
                return new List<SimpleVoxel>();
            }

            HashSet<VoxelChunk> tempVoxelChunks = data1.Item2;

            foreach (var item in tempVoxelChunks)
            {
                item.GetMyMesh();
            }

            foreach (var item in tempVoxelChunks)
            {
                if (item.isWrite)
                {

                }
                else
                {
                    mainGameObjectChunks[item.Key] = new EntityChunk(item.chunkPosition, mainMaterial, mainTransform);
                    item.isWrite = true;
                }
                if (!tempGameObjectChunks.ContainsKey(item.Key))
                {
                    tempGameObjectChunks[item.Key] = mainGameObjectChunks[item.Key];
                }

                MyMesh myMesh = item.overMyMesh;
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);

                //chunkMesh.RecalculateNormals();
                mainGameObjectChunks[item.Key].Update(myMesh);
            }
            return data1.Item3;
        }

        public Tuple<List<SimpleVoxel>, List<SimpleVoxel>> DrawPaintBlock(IEnumerable<Vector3Int> positions, int uvKey)
        {
            List<SimpleVoxel> fronts = new List<SimpleVoxel>();
            List<SimpleVoxel> breaks = new List<SimpleVoxel>();

            Dictionary<int, VoxelChunk> tempVoxelChunks = new Dictionary<int, VoxelChunk>();
            foreach (Vector3Int position in positions)
            {
                Voxel3D voxle;
                if (allVoxels.TryGetValue(position, out voxle))
                {
                    //mainVoxelChunkSurfaces
                    VoxelChunk voxelChunk = mainDictionaryVoxelChunks[voxle.chunkKey.GetHashCode()];
                    if (tempVoxelChunks.ContainsKey(voxelChunk.GetHashCode()))
                    {

                    }
                    else
                    {
                        tempVoxelChunks[voxelChunk.GetHashCode()] = voxelChunk;
                    }
                    if (voxle.uvKey == uvKey)
                    {

                    }
                    else
                    {
                        //bool isok = false;
                        for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
                        {
                            if (voxle.surfaces[i])
                            {
                                voxelChunk.UpdateUV(i, voxle.chunkIndex, uvKey);
                                //isok = true;
                            }
                        }
                        //if (isok)
                        {
                            fronts.Add(new SimpleVoxel(voxle.worldPosition, voxle.uvKey, voxle.selectKey));
                            breaks.Add(new SimpleVoxel(voxle.worldPosition, uvKey, voxle.selectKey));
                        }
                        voxle.uvKey = uvKey;
                    }
                }
            }


            foreach (var chunk in tempVoxelChunks)
            {
                MyMesh myMesh = chunk.Value.GetUVMyMesh();
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
                //chunkMesh.RecalculateNormals();
                mainGameObjectChunks[chunk.Key].Update(myMesh);
            }
            return Tuple.Create(fronts, breaks);
        }

        public void DrawPaintBlock(IEnumerable<SimpleVoxel> datas)
        {
            Dictionary<int, VoxelChunk> tempVoxelChunks = new Dictionary<int, VoxelChunk>();
            foreach (SimpleVoxel data in datas)
            {
                Voxel3D voxle;
                if (allVoxels.TryGetValue(data.position, out voxle))
                {
                    //mainVoxelChunkSurfaces
                    VoxelChunk voxelChunk = mainDictionaryVoxelChunks[voxle.chunkKey.GetHashCode()];
                    if (tempVoxelChunks.ContainsKey(voxelChunk.GetHashCode()))
                    {

                    }
                    else
                    {
                        tempVoxelChunks[voxelChunk.GetHashCode()] = voxelChunk;
                    }

                    if (voxle.uvKey == data.uvKey)
                    {

                    }
                    else
                    {

                        for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
                        {
                            if (voxle.surfaces[i])
                            {
                                voxelChunk.UpdateUV(i, voxle.chunkIndex, data.uvKey);
                            }
                        }
                        voxle.uvKey = data.uvKey;
                    }

                }
            }


            foreach (var chunk in tempVoxelChunks)
            {
                MyMesh myMesh = chunk.Value.GetUVMyMesh();
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
                //chunkMesh.RecalculateNormals();
                mainGameObjectChunks[chunk.Key].Update(myMesh);
            }
        }

        public List<Vector3Int> ClearAllSelect()
        {
            List<Vector3Int> overPositons = new List<Vector3Int>();
            Dictionary<int, VoxelChunk> tempVoxelChunks = new Dictionary<int, VoxelChunk>();
            foreach (var item in allVoxels.dictionaryVoxelChunks.Values)
            {
                var voxelChunk = item;
                bool isHave = false;
                foreach (Voxel3D voxel in voxelChunk.mainVoxels)
                {
                    if (voxel != null && voxel.selectKey == 1)
                    {
                        isHave = true;
                        overPositons.Add(voxel.worldPosition);
                        voxel.selectKey = 255;
                        for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
                        {
                            if (voxel.surfaces[i])
                            {
                                voxelChunk.UpdateColors(i, voxel.chunkIndex, 255);
                            }
                        }
                    }
                }
                if (isHave)
                {
                    tempVoxelChunks[item.Key] = voxelChunk;
                }
            }
            foreach (var chunk in tempVoxelChunks)
            {
                MyMesh myMesh = chunk.Value.GetColorsMyMesh();
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
                mainGameObjectChunks[chunk.Key].Update(myMesh);
            }
            tempVoxelChunks.Clear();
            return overPositons;
        }

        public List<Vector3Int> DrawSelect(IEnumerable<Vector3Int> positions, byte uv2Key)
        {
            if (positions.Count() > 0)
            {
            }

            List<Vector3Int> overPositons = new List<Vector3Int>();
            Dictionary<int, VoxelChunk> tempVoxelChunks = new Dictionary<int, VoxelChunk>();
            foreach (Vector3Int position in positions)
            {
                Voxel3D voxle;
                if (allVoxels.TryGetValue(position, out voxle))
                {
                    //mainVoxelChunkSurfaces
                    VoxelChunk voxelChunk = mainDictionaryVoxelChunks[voxle.chunkKey.GetHashCode()];
                    if (tempVoxelChunks.ContainsKey(voxelChunk.GetHashCode()))
                    {

                    }
                    else
                    {
                        tempVoxelChunks[voxelChunk.GetHashCode()] = voxelChunk;
                    }
                    if (voxle.selectKey == uv2Key)
                    {

                    }
                    else
                    {
                        voxle.selectKey = uv2Key;
                        for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
                        {
                            if (voxle.surfaces[i])
                            {
                                voxelChunk.UpdateColors(i, voxle.chunkIndex, uv2Key);
                            }
                        }
                        overPositons.Add(position);
                    }
                }
            }
            foreach (var chunk in tempVoxelChunks)
            {
                MyMesh myMesh = chunk.Value.GetColorsMyMesh();
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
                mainGameObjectChunks[chunk.Key].Update(myMesh);
            }
            return overPositons;
        }


        /*
        public Tuple<List<SimpleVoxel>, List<SimpleVoxel>> DrawAddOrPaintBlock(IEnumerable<Vector3Int> blocks, int uvKey)
        {
            List<SimpleVoxel> fronts = new List<SimpleVoxel>();
            List<SimpleVoxel> breaks;
            Dictionary<int, VoxelChunk> updateVoxelChunks;

            var data1 = AddOrPaintBlocks(blocks, uvKey);

            if (data1.Item1 == false)
            {
                updateVoxelChunks = new Dictionary<int, VoxelChunk>();
                breaks = new List<SimpleVoxel>();
            }
            else
            {
                updateVoxelChunks = data1.Item2;
                breaks = data1.Item3;
            }
            var paintBlocks = data1.Item4;

            foreach (var voxle in paintBlocks)
            {
                VoxelChunk voxelChunk = mainDictionaryVoxelChunks[voxle.chunkPosition.GetHashCode()];
                if (updateVoxelChunks.ContainsKey(voxelChunk.GetHashCode()))
                {

                }
                else
                {
                    updateVoxelChunks[voxelChunk.GetHashCode()] = voxelChunk;
                }
                if (voxle.uvKey == uvKey)
                {

                }
                else
                {
                    //bool isok = false;
                    for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
                    {
                        if (voxle.surfaces[i])
                        {
                            voxelChunk.UpdateUV(i, voxle.chunkIndex, uvKey);
                            //isok = true;
                        }
                    }
                    //if (isok)
                    {
                        fronts.Add(new SimpleVoxel(voxle.worldPosition, voxle.uvKey, voxle.selectKey));
                        voxle.uvKey = uvKey;
                        breaks.Add(new SimpleVoxel(voxle.worldPosition, uvKey, voxle.selectKey));
                    }
                }
            }


            foreach (var chunk in updateVoxelChunks)
            {
                if (chunk.Value.isWrite)
                {

                }
                else
                {
                    mainGameObjectChunks[chunk.Key] = new EntityChunk(chunk.Value.chunkPosition, mainMaterial, mainTransform);
                    chunk.Value.isWrite = true;
                }
                if (!tempGameObjectChunks.ContainsKey(chunk.Key))
                {
                    tempGameObjectChunks[chunk.Key] = mainGameObjectChunks[chunk.Key];
                }

                MyMesh myMesh = chunk.Value.GetMyMesh();
                myMesh.triangles = m_VoxelMetadata3D.GetTris(myMesh.vertices.Length / VoxelCategories.UNIT_VERTICES_LENGTH);
                mainGameObjectChunks[chunk.Key].Update(myMesh);
            }
            return Tuple.Create(fronts, breaks);
        }
        */

        Vector3Int GetLocalPosition(Vector3Int point)
        {
            int localX = point.x & VoxelCategories.CHUNK_UNIT_LENGTH_Minus1;
            int localY = point.y & VoxelCategories.CHUNK_UNIT_LENGTH_Minus1;
            int localZ = point.z & VoxelCategories.CHUNK_UNIT_LENGTH_Minus1;
            return new Vector3Int(localX, localY, localZ);
        }


        Vector3Int GetChunkPosition(Vector3Int point,out int key)
        {
            int chunkX = point.x >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int chunkY = point.y >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int chunkZ = point.z >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            key = (chunkX + 8) + (chunkY) * 16 + (chunkZ + 8) * 256;
            return new Vector3Int(chunkX, chunkY, chunkZ);
        }


        int GetChunkKey(Vector3Int point)
        {
            int chunkX = point.x >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int chunkY = point.y >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            int chunkZ = point.z >> VoxelCategories.CHUNK_UNIT_LENGTH_BIT;
            return (chunkX + 8) + (chunkY) * 16 + (chunkZ + 8) * 256;
        }

        private Tuple<bool , HashSet<VoxelChunk>, SimpleVoxel[]> AddBlocks(IEnumerable<Voxel3D> voxel3Ds)
        {
            List<Voxel3D> allTrueVoxels = new List<Voxel3D>(voxel3Ds.Count());
            HashSet<VoxelChunk> tempVoxelChunks = new HashSet<VoxelChunk>();

            //添加block,并获得要删除的面数据
            foreach (Voxel3D item in voxel3Ds)
            {
                if (AddBlockCalculationRemoveIndex(item, tempVoxelChunks))
                {
                    allTrueVoxels.Add(item);
                }
            }
            if (allTrueVoxels.Count == 0)
            {
                return Tuple.Create<bool, HashSet<VoxelChunk>, SimpleVoxel[]>(false, null, null);
            }


            for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
            {
                int index = i;
                foreach (var item in tempVoxelChunks)
                {
                    CalculationBlockAddData(tempVoxelChunks, item, index);
                    item.Update(index);
                }
            }


            //通知数据已完成写入
            foreach (var item in allTrueVoxels)
            {
                item.isWrite = true;
	        }



         //   /* shadows
            foreach (var item in tempAllUpdateShadow)
            {
                mainDictionaryVoxelChunks[item.chunkID].UpdateShadowColors(item.direction, item.chunkIndex, item.shadow);
            }
            tempAllUpdateShadow.Clear();

            foreach (var item in tempShadowVoxelChunks)
            {
                var uv3 = item.Value.GetUV3().uv3;
                mainGameObjectChunks[item.Key].UpdateUV3(uv3);
            }
            tempShadowVoxelChunks.Clear();
            // */


            foreach (var item in tempVoxelChunks)
            {
                item.SurfaceUpdateDatas.Clear();
                item.tempVoxels.Clear();
            }


            SimpleVoxel[] returnSerializeVoxelArray = new SimpleVoxel[allTrueVoxels.Count];
            for (int i = 0, max = allTrueVoxels.Count; i < max; i++)
            {
                Voxel3D voxel3D = allTrueVoxels[i];
                returnSerializeVoxelArray[i] = new SimpleVoxel(voxel3D.worldPosition, voxel3D.uvKey, voxel3D.selectKey);
            }
            return Tuple.Create<bool, HashSet<VoxelChunk>, SimpleVoxel[]>(true, tempVoxelChunks, returnSerializeVoxelArray);
        }

        private HashSet<VoxelChunk> AddBlocks(IEnumerable<SimpleVoxel> voxel3Ds)
        {
            List<Voxel3D> allTrueVoxels = new List<Voxel3D>(voxel3Ds.Count());
            HashSet<VoxelChunk> tempVoxelChunks = new HashSet<VoxelChunk>();

            //添加block,并获得要删除的面数据
            foreach (SimpleVoxel item in voxel3Ds)
            {
                var voxel = new Voxel3D(item.position, item.uvKey, item.selectKey);
                if (AddBlockCalculationRemoveIndex(voxel, tempVoxelChunks))
                {
                    allTrueVoxels.Add(voxel);
                }
            }
            if (allTrueVoxels.Count == 0)
            {
                return tempVoxelChunks;
            }


            for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
            {
                int index = i;
                foreach (var item in tempVoxelChunks)
                {
                    CalculationBlockAddData(tempVoxelChunks, item, index);
                    item.Update(index);
                }
            }

            //通知数据已完成写入
            foreach (var item in allTrueVoxels)
            {
                item.isWrite = true;
            }

            foreach (var item in tempVoxelChunks)
            {
                item.SurfaceUpdateDatas.Clear();
                item.tempVoxels.Clear();
            }
            return tempVoxelChunks;
        }


        public List<SimpleVoxel> Separate()
        {
            List<Vector3Int> overPositons = new List<Vector3Int>();
            foreach (var item in allVoxels.Values)
            {
                if (item.selectKey == 1)
                {
                    overPositons.Add(item.worldPosition);
                }
            }
            List<SimpleVoxel> list = DrawRemoveBlock(overPositons);
            return list;
        }
        //private Tuple<bool, Dictionary<int, VoxelChunk>, List<SimpleVoxel>, List<Voxel3D>> AddOrPaintBlocks(IEnumerable<Vector3Int> blocks, int uvKey)
        //{
        //    List<Voxel3D> paintVoxels = new List<Voxel3D>();
        //    List<Voxel3D> allTrueVoxels = new List<Voxel3D>(blocks.Count());
        //    Dictionary<int, VoxelChunk> parentDictionaryVoxelChunks = this.mainDictionaryVoxelChunks;
        //    Dictionary<int, VoxelChunk> tempVoxelChunks = new Dictionary<int, VoxelChunk>();

        //    //添加block,并获得要删除的面数据
        //    foreach (Vector3Int item in blocks)
        //    {
        //        Voxel3D voxel;//= new Voxel3D(item, uvKey);
        //        if (allVoxels.TryGetValue(item, out voxel))
        //        {
        //            paintVoxels.Add(voxel);
        //        }
        //        else
        //        {
        //            voxel = new Voxel3D(item, uvKey);
        //            AddBlockCalculationRemoveIndex(voxel, parentDictionaryVoxelChunks, tempVoxelChunks);
        //            allTrueVoxels.Add(voxel);
        //        }
        //    }
        //    if (allTrueVoxels.Count == 0)
        //    {
        //        return Tuple.Create<bool, Dictionary<int, VoxelChunk>, List<SimpleVoxel>, List<Voxel3D>>(false, null, null, paintVoxels);
        //    }


        //    //   
        //    var datas = tempVoxelChunks.Values.ToArray();
        //    //System.Threading.Tasks.Task[] var_Array_Tasks = new System.Threading.Tasks.Task[VoxelCategories.SURFACE_LENGTH];
        //    for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
        //    {
        //        int index = i;
        //        //var_Array_Tasks[i] = new System.Threading.Tasks.Task(
        //        //    () =>
        //        //    {
        //                foreach (var item in datas)
        //                {
        //                    CalculationBlockAddData(tempVoxelChunks, item, index);
        //                    item.Update(index);
        //                }
        //            //}
        //        //);
        //        //var_Array_Tasks[i].Start();
        //    }
        //    //System.Threading.Tasks.Task.WaitAll(var_Array_Tasks);


        //    //通知数据已完成写入
        //    foreach (var item in allTrueVoxels)
        //    {
        //        item.isWrite = true;
        //    }
        //    //通知数据已完成写入
        //    //Parallel.ForEach(allTrueVoxels, item =>
        //    //{
        //    //    item.isWrite = true;
        //    //});

        //    foreach (var item in tempVoxelChunks.Values)
        //    {
        //        item.SurfaceUpdateDatas.Clear();
        //        item.tempVoxels.Clear();
        //    }
        //    //Parallel.ForEach(tempVoxelChunks.Values, item =>
        //    //{
        //    //    item.SurfaceUpdateDatas.Clear();
        //    //    item.tempVoxels.Clear();
        //    //});

        //    List<SimpleVoxel> returnSerializeVoxelArray = new List<SimpleVoxel>(allTrueVoxels.Count);
        //    for (int i = 0, max = allTrueVoxels.Count; i < max; i++)
        //    {
        //        Voxel3D voxel3D = allTrueVoxels[i];
        //        returnSerializeVoxelArray.Add(new SimpleVoxel(voxel3D.worldPosition, voxel3D.uvKey, voxel3D.selectKey));
        //    }
        //    return Tuple.Create(true, tempVoxelChunks, returnSerializeVoxelArray, paintVoxels);
        //}

        /// <summary>
        /// 添加block,并计算出添加block需要删除之前的哪些面
        /// </summary>
        /// <param name="voxel3D"></param>
        /// <param name="mainDictionaryVoxelChunks"></param>
        /// <param name="tempVoxelChunks"></param>
        /// <returns>是否应该添加</returns>
        private bool AddBlockCalculationRemoveIndex(Voxel3D voxel3D,
            HashSet<VoxelChunk> tempVoxelChunks
            )
        {
            if (voxel3D == null || allVoxels.ContainsKey(voxel3D.worldPosition)
                || AddBlockIsContinue(voxel3D.worldPosition) //  || voxel3D.IsBorder || voxel3D.worldPosition.x < 0 || voxel3D.worldPosition.y < 0 || voxel3D.worldPosition.z < 0
                )
            {
                return false;
            }
            else
            {
            }
            int chunkKey;
            Vector3Int chunkPosition = GetChunkPosition(voxel3D.worldPosition, out chunkKey);

            //计算相对坐标
            Vector3Int localPosition = GetLocalPosition(voxel3D.worldPosition);
            //在数据中赋值
            voxel3D.StartData(localPosition);

            VoxelChunk voxelChunk;
            if (mainDictionaryVoxelChunks.TryGetValue(chunkKey, out voxelChunk))
            {
                tempVoxelChunks.Add(voxelChunk);
            }
            else
            {
                voxelChunk = mainDictionaryVoxelChunks[chunkKey] = new VoxelChunk(chunkPosition);
                tempVoxelChunks.Add(voxelChunk);
            }


            voxelChunk.mainVoxels[voxel3D.chunkIndex] = voxel3D;
            voxelChunk.tempVoxels.Add(voxel3D);
            allVoxels[voxel3D.worldPosition] = voxel3D;

            voxel3D.chunkKey = voxelChunk.Key;
            voxel3D.isWrite = false;


            int[] conjugateVoxel3DIndexs = VoxelMetadata3D.ConjugateDirectionIndexs;
            for (int directionIndex = 0; directionIndex < VoxelCategories.SURFACE_LENGTH; directionIndex++)
            {
                Voxel3D conjugateVoxel3D = allVoxels[voxel3D.GetWorldIndex(directionIndex)];
                if (conjugateVoxel3D == null)
                {
                    voxel3D.surfaces[directionIndex] = true;
                }
                else
                {
                    voxel3D.surfaces[directionIndex] = false;
                    if (conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]])
                    {
                        conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] = false;
                        if (conjugateVoxel3D.isWrite)
                        {
                            int conjugateKey = conjugateVoxel3D.chunkKey;
                            if (conjugateKey == chunkKey)
                            {
                                voxelChunk.SurfaceUpdateDatas.removeIndexs[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel3D.chunkIndex);
                            }
                            else
                            {
                                VoxelChunk conjugateVoxelChunk;
                                if (mainDictionaryVoxelChunks.TryGetValue(conjugateKey, out conjugateVoxelChunk))
                                {
                                    conjugateVoxelChunk.SurfaceUpdateDatas.removeIndexs[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel3D.chunkIndex);
                                    tempVoxelChunks.Add(conjugateVoxelChunk);
                                }
                            }
                        }
                    }
                }
            }
            /*

            List<int>[] removeIndex = voxelChunk.SurfaceUpdateDatas.removeIndexs;

            if (voxel3D.IsBorder)
            {
                int[] conjugateVoxel3DIndexs = VoxelMetadata3D.ConjugateDirectionIndexs;
                for (int directionIndex = 0; directionIndex < VoxelCategories.SURFACE_LENGTH; directionIndex++)
                {
                    if (voxel3D.specificBorders[directionIndex])
                    {
                        int conjugateKey = DrawVoxel3DCore.Vector3IntHashCodeChange(voxelChunk.GetHashCode(), directionIndex, 1);
                        VoxelChunk conjugateVoxelChunk;

                        if (dictionaryVoxelChunks.TryGetValue(conjugateKey, out conjugateVoxelChunk))
                        {
                            var conjugateVoxel = conjugateVoxelChunk.mainVoxels[voxel3D.GetChunkIndexBorderChunkConjugate(directionIndex)];

                            if (conjugateVoxel == null)
                            {
                                voxel3D.surfaces[directionIndex] = true;
                                continue;
                            }
                            else
                            {
                                voxel3D.surfaces[directionIndex] = false;
                                if (conjugateVoxel.surfaces[conjugateVoxel3DIndexs[directionIndex]])
                                {
                                    conjugateVoxel.surfaces[conjugateVoxel3DIndexs[directionIndex]] = false;
                                    if (conjugateVoxel.isWrite)
                                    {
                                        VoxelChunk conjugateVoxelChunkSurfaceUpdateDatas;
                                        if (tempVoxelChunks.TryGetValue(conjugateKey, out conjugateVoxelChunkSurfaceUpdateDatas))
                                        {

                                        }
                                        else
                                        {
                                            conjugateVoxelChunkSurfaceUpdateDatas = tempVoxelChunks[conjugateKey] = dictionaryVoxelChunks[conjugateKey];
                                            //conjugateVoxelChunkSurfaceUpdateDatas.SurfaceUpdateDatas.Clear();
                                        }
                                        List<int>[] conjugateRemoveIndex = conjugateVoxelChunkSurfaceUpdateDatas.SurfaceUpdateDatas.removeIndexs;
                                        conjugateRemoveIndex[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel.chunkIndex);
                                    }
                                }
                            }
                        }
                        else
                        {
                            voxel3D.surfaces[directionIndex] = true;
                        }
                    }
                    else
                    {
                        //做非边境处理
                        var conjugateVoxel = voxelChunk.mainVoxels[voxel3D.GetChunkIndexNoBorder(directionIndex)];
                        if (conjugateVoxel == null)
                        {
                            voxel3D.surfaces[directionIndex] = true;

                        }
                        else
                        {
                            voxel3D.surfaces[directionIndex] = false;
                            if (conjugateVoxel.surfaces[conjugateVoxel3DIndexs[directionIndex]])
                            {
                                conjugateVoxel.surfaces[conjugateVoxel3DIndexs[directionIndex]] = false;
                                if (conjugateVoxel.isWrite)
                                {
                                    removeIndex[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel.chunkIndex);
                                }
                            }
                        }
                    }

                }//for end


            }
            else
            {
                int[] conjugateVoxel3DIndexs = VoxelMetadata3D.ConjugateDirectionIndexs;
                for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
                {
                    Voxel3D conjugateVoxel3D = voxelChunk.mainVoxels[voxel3D.GetChunkIndexNoBorder(i)];
                    if (conjugateVoxel3D == null)
                    {
                        voxel3D.surfaces[i] = true;
                    }
                    else
                    {
                        voxel3D.surfaces[i] = false;
                        if (conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[i]])
                        {
                            conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[i]] = false;
                            if (conjugateVoxel3D.isWrite)
                            {
                                removeIndex[conjugateVoxel3DIndexs[i]].Add(conjugateVoxel3D.chunkIndex);
                            }
                        }
                    }
                }
            }
            */
            return true;
        }

        /// <summary>
        /// 计算新添加的block所带来的新的面数据
        /// </summary>
        /// <param name="voxel3D"></param>
        /// <param name="addIndexs"></param>
        /// <param name="addData_True"></param>
        //private void CalculationBlockAddData(Voxel3D voxel3D,
        //     Dictionary<int, VoxelChunk> dictionaryVoxelChunks)
        //{
        //    // List<int>[] addIndexs, List<Vector3[]>[] addData_True

        //    VoxelChunkSurfaceUpdateDatas voxelChunkSurfaceUpdateDatas =
        //        dictionaryVoxelChunks[voxel3D.chunkPosition.GetHashCode()].SurfaceUpdateDatas;
        //    for (int i = 0; i < 6; i++)
        //    {
        //        if (voxel3D.m_Array_Surface[i])
        //        {
        //            voxelChunkSurfaceUpdateDatas.addIndexs[i].Add(voxel3D.m_ChunkIndex);

        //            voxelChunkSurfaceUpdateDatas.addDatasVertices[i].Add(
        //               VoxelMetadata3D.m_instance.GetVertices(i, voxel3D.position)
        //            );
        //            voxelChunkSurfaceUpdateDatas.addDatasUVs[i].Add(
        //               VoxelMetadata3D.m_instance.GetUV(voxel3D.m_UV)
        //            );

        //            voxelChunkSurfaceUpdateDatas.addDatasColors[i].Add(
        //              VoxelMetadata3D.m_instance.GetColors(i,voxel3D.colorShadow[i])
        //           );
        //        }
        //    }
        //}

        private void CalculationBlockAddData(
            HashSet<VoxelChunk> tempVoxelChunks,
            VoxelChunk voxelChunk,
            int direction
            )
        {
            var voxelChunkSurfaceUpdateDatas = voxelChunk.SurfaceUpdateDatas;
            foreach (Voxel3D voxel3D in voxelChunk.tempVoxels)
            {
                if (voxel3D.surfaces[direction])
                {
                    voxelChunkSurfaceUpdateDatas.addIndexs[direction].Add(voxel3D.chunkIndex);
                    SetBlockShadowAdd(voxel3D, voxelChunk, direction, tempVoxelChunks);
                }
            }
        }


        private Dictionary<int, VoxelChunk> tempShadowVoxelChunks = new Dictionary<int, VoxelChunk>();
        private List<UpdateShadowUnitData> tempAllUpdateShadow = new List<UpdateShadowUnitData>();

        private void SetBlockShadowAdd(Voxel3D voxel3D, VoxelChunk voxelChunk, int direction, HashSet<VoxelChunk> tempVoxelChunks)
        {
            int[] edgeIndexs = VoxelMetadata3D.voxel3DEdgeIndex[direction];
            for (int edgeIndex = 0; edgeIndex < VoxelCategories.UNIT_VERTICES_LENGTH; edgeIndex++)
            {
                Voxel3D edgeConjugate = allVoxels[voxel3D.worldIndex + edgeIndexs[edgeIndex]];
                if (edgeConjugate == null)
                {

                }
                else
                {
                    voxel3D.SetColorShadowAdd(direction, edgeIndex, edgeConjugate, tempAllUpdateShadow);
                    if (edgeConjugate.chunkKey != voxel3D.chunkKey)
                    {
                        if (tempShadowVoxelChunks.ContainsKey(edgeConjugate.chunkKey) == false)
                        {
                            var edgeConjugateChunk = mainDictionaryVoxelChunks[edgeConjugate.chunkKey];
                            if (tempVoxelChunks.Contains(edgeConjugateChunk) == false)
                            {
                                tempShadowVoxelChunks[edgeConjugate.chunkKey] = edgeConjugateChunk;
                            }
                        }
                    }
                }
            }

            int[] cornerIndexs = VoxelMetadata3D.voxel3DCornerIndex[direction];
            for (int edgeIndex = 0; edgeIndex < cornerIndexs.Length; edgeIndex++)
            {
                Voxel3D edgeConjugate = allVoxels[voxel3D.worldIndex + cornerIndexs[edgeIndex]];
                if (edgeConjugate == null)
                {
                }
                else
                {
                    voxel3D.SetColorShadowCornerAdd(direction, edgeIndex, edgeConjugate, tempAllUpdateShadow);
                    if (edgeConjugate.chunkKey != voxel3D.chunkKey)
                    {
                        if (tempShadowVoxelChunks.ContainsKey(edgeConjugate.chunkKey) == false)
                        {
                            var edgeConjugateChunk = mainDictionaryVoxelChunks[edgeConjugate.chunkKey];
                            if (tempVoxelChunks.Contains(edgeConjugateChunk) == false)
                            {
                                tempShadowVoxelChunks[edgeConjugate.chunkKey] = edgeConjugateChunk;
                            }
                        }
                    }
                }
            }
        }

        private void SetBlockShadowRemove(Voxel3D voxel3D, VoxelChunk voxelChunk, int direction, HashSet<VoxelChunk> tempVoxelChunks)
        {
            int[] edgeIndexs = VoxelMetadata3D.voxel3DEdgeIndex[direction];
            for (int edgeIndex = 0; edgeIndex < VoxelCategories.UNIT_VERTICES_LENGTH; edgeIndex++)
            {
                Voxel3D edgeConjugate = allVoxels[voxel3D.worldIndex + edgeIndexs[edgeIndex]];
                if (edgeConjugate == null)
                {

                }
                else
                {
                    voxel3D.SetColorShadowRemove(direction, edgeIndex, edgeConjugate, tempAllUpdateShadow);
                    if (edgeConjugate.chunkKey != voxel3D.chunkKey)
                    {
                        if (tempShadowVoxelChunks.ContainsKey(edgeConjugate.chunkKey) == false)
                        {
                            var edgeConjugateChunk = mainDictionaryVoxelChunks[edgeConjugate.chunkKey];
                            if (tempVoxelChunks.Contains(edgeConjugateChunk) == false)
                            {
                                tempShadowVoxelChunks[edgeConjugate.chunkKey] = edgeConjugateChunk;
                            }
                        }
                    }
                }
            }

            int[] cornerIndexs = VoxelMetadata3D.voxel3DCornerIndex[direction];
            for (int edgeIndex = 0; edgeIndex < cornerIndexs.Length; edgeIndex++)
            {
                Voxel3D edgeConjugate = allVoxels[voxel3D.worldIndex + cornerIndexs[edgeIndex]];
                if (edgeConjugate == null)
                {
                }
                else
                {
                    voxel3D.SetColorShadowCornerRemove(direction, edgeIndex, edgeConjugate, tempAllUpdateShadow);
                    if (edgeConjugate.chunkKey != voxel3D.chunkKey)
                    {
                        if (tempShadowVoxelChunks.ContainsKey(edgeConjugate.chunkKey) == false)
                        {
                            var edgeConjugateChunk = mainDictionaryVoxelChunks[edgeConjugate.chunkKey];
                            if (tempVoxelChunks.Contains(edgeConjugateChunk) == false)
                            {
                                tempShadowVoxelChunks[edgeConjugate.chunkKey] = edgeConjugateChunk;
                            }
                        }
                    }
                }
            }

        }

        private Tuple<bool, HashSet<VoxelChunk>, List<SimpleVoxel>> RemoveBlocks(IEnumerable<Vector3Int> positions)
        {
            HashSet<VoxelChunk> tempVoxelChunks = new HashSet<VoxelChunk>();
            List<Voxel3D> removeVoxel = new List<Voxel3D>();
            List<SimpleVoxel> returnSerializeRemoveVoxel = new List<SimpleVoxel>();

            //通知数据开始删除

            foreach (Vector3Int position in positions)
            {
                Voxel3D voxel3D;
                if (allVoxels.TryGetValue(position, out voxel3D))
                {
                    voxel3D.isWrite = false;
                    removeVoxel.Add(voxel3D);
                    returnSerializeRemoveVoxel.Add(new SimpleVoxel(voxel3D.worldPosition, voxel3D.uvKey, voxel3D.selectKey));
                    allVoxels[position] = null;
                }
            }

            if (removeVoxel.Count == 0)
            {
                return Tuple.Create<bool, HashSet<VoxelChunk>, List<SimpleVoxel>>(false, null, null);
            }

            //添加block,并获得要删除的面数据
            foreach (Voxel3D item in removeVoxel)
            {
                RemoveBlockCalculation(item, tempVoxelChunks);
            }

          //  /* shadows
            foreach (TempShadow item in allRemoveTempShadows)
            {
                SetBlockShadowRemove(item.voxel3D, item.voxelChunk, item.directionIndex, tempVoxelChunks);
            }
            foreach (TempShadow item in allAddTempShadows)
            {
                item.voxel3D.SetNewColorShadow(item.directionIndex);
                SetBlockShadowAdd(item.voxel3D, item.voxelChunk, item.directionIndex, tempVoxelChunks);
            }

            allRemoveTempShadows.Clear();
            allAddTempShadows.Clear();
           //  */

            //foreach (Voxel3D voxel3D in removeVoxel)
            //{
            //    for (int direction = 0; direction < 6; direction++)
            //    {
            //        //if (voxel3D.surfaces[direction])
            //        //{
            //        //    SetBlockShadowRemove(voxel3D, mainDictionaryVoxelChunks[voxel3D.chunkPosition.GetHashCode()], direction, tempVoxelChunks);
            //        //}
            //        //else
            //        //{
            //        //    Voxel3D directionVoxel3D = allVoxels[voxel3D.worldPosition + VoxelMetadata3D.ConjugateDirectionVector3Ints[direction]];
            //        //    SetBlockShadowAdd(directionVoxel3D, mainDictionaryVoxelChunks[directionVoxel3D.chunkPosition.GetHashCode()], VoxelMetadata3D.ConjugateDirectionIndexs[direction], tempVoxelChunks);
            //        //}
            //    }
            //}


            for (int i = 0; i < VoxelCategories.SURFACE_LENGTH; i++)
            {
                foreach (var item in tempVoxelChunks)
                {
                    item.Update(i);
                }
            }


            foreach (var item in tempAllUpdateShadow)
            {
                mainDictionaryVoxelChunks[item.chunkID].UpdateShadowColors(item.direction, item.chunkIndex, item.shadow);
            }
            tempAllUpdateShadow.Clear();

            foreach (var item in tempShadowVoxelChunks)
            {
                var uv3 = item.Value.GetUV3().uv3;
                mainGameObjectChunks[item.Key].UpdateUV3(uv3);
            }
            tempShadowVoxelChunks.Clear();


            foreach (var item in tempVoxelChunks)
            {
                item.SurfaceUpdateDatas.Clear();
                //item.tempVoxels.Clear();
            }

            return Tuple.Create<bool, HashSet<VoxelChunk>, List<SimpleVoxel>>(true, tempVoxelChunks, returnSerializeRemoveVoxel);
        }


        struct TempShadow {
            public Voxel3D voxel3D;
            public VoxelChunk voxelChunk;
            public int directionIndex;
            public TempShadow(Voxel3D voxel3D, VoxelChunk voxelChunk, int directionIndex)
            {
                this.voxel3D = voxel3D;
                this.voxelChunk = voxelChunk;
                this.directionIndex = directionIndex;
            }
        }

        /// <summary>
        /// 临时的OA光影添加
        /// </summary>
        List<TempShadow> allAddTempShadows = new List<DrawVoxel3DCore.TempShadow>();
        /// <summary>
        /// 临时的OA光影删除
        /// </summary>
        List<TempShadow> allRemoveTempShadows = new List<DrawVoxel3DCore.TempShadow>();

        private void RemoveBlockCalculation(Voxel3D voxel3D,
           HashSet<VoxelChunk> tempVoxelChunks
          )
        {
            int chunkKey = voxel3D.chunkKey;

            VoxelChunk voxelChunk;
            if (mainDictionaryVoxelChunks.TryGetValue(chunkKey, out voxelChunk))
            {
                tempVoxelChunks.Add(voxelChunk);
            }
            else
            {
                return;
            }

            int[] conjugateVoxel3DIndexs = VoxelMetadata3D.ConjugateDirectionIndexs;
            for (int directionIndex = 0; directionIndex < VoxelCategories.SURFACE_LENGTH; directionIndex++)
            {
                if (voxel3D.surfaces[directionIndex])
                {
                    voxelChunk.SurfaceUpdateDatas.removeIndexs[directionIndex].Add(voxel3D.chunkIndex);
                    allRemoveTempShadows.Add(new TempShadow(voxel3D, voxelChunk, directionIndex));
                }
                else
                {
                    Voxel3D conjugateVoxel3D = allVoxels[voxel3D.GetWorldIndex(directionIndex)];
                    if (conjugateVoxel3D == null)
                    {
                    }
                    else
                    {
                        if (conjugateVoxel3D.isWrite)
                        {
                            if (conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] == false)
                            {
                                conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] = true;

                                if (conjugateVoxel3D.chunkKey == chunkKey)
                                {
                                    voxelChunk.SurfaceUpdateDatas.addIndexs[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel3D.chunkIndex);
                                    allAddTempShadows.Add(new TempShadow(conjugateVoxel3D, voxelChunk, conjugateVoxel3DIndexs[directionIndex]));
                                }
                                else
                                {
                                    tempVoxelChunks.Add(mainDictionaryVoxelChunks[conjugateVoxel3D.chunkKey]);
                                    mainDictionaryVoxelChunks[conjugateVoxel3D.chunkKey].SurfaceUpdateDatas.addIndexs[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel3D.chunkIndex);
                                    allAddTempShadows.Add(new TempShadow(conjugateVoxel3D, mainDictionaryVoxelChunks[conjugateVoxel3D.chunkKey], conjugateVoxel3DIndexs[directionIndex]));
                                }
                            }
                        }
                    }
                }
            }
            /*
            List<int>[] removeIndex = voxelChunk.SurfaceUpdateDatas.removeIndexs;
            List<int>[] addIndex = voxelChunk.SurfaceUpdateDatas.addIndexs;

            int[] conjugateVoxel3DIndexs = VoxelMetadata3D.ConjugateDirectionIndexs;
            if (voxel3D.IsBorder)
            {
                //return;
                for (int directionIndex = 0; directionIndex < VoxelCategories.SURFACE_LENGTH; directionIndex++)
                {
                    if (voxel3D.specificBorders[directionIndex])
                    {
                        int conjugateKey = DrawVoxel3DCore.Vector3IntHashCodeChange(voxelChunk.GetHashCode(), directionIndex, 1);
                        VoxelChunk conjugateVoxelChunk;

                        if (mainDictionaryVoxelChunks.TryGetValue(conjugateKey, out conjugateVoxelChunk))
                        {
                            var conjugateVoxel = conjugateVoxelChunk.mainVoxels[voxel3D.GetChunkIndexBorderChunkConjugate(directionIndex)];

                            if (conjugateVoxel == null)
                            {
                                if (voxel3D.surfaces[directionIndex])
                                {
                                    removeIndex[directionIndex].Add(voxel3D.chunkIndex);
                                    allRemoveTempShadows.Add(new TempShadow(voxel3D, conjugateVoxelChunk, directionIndex));
                                }
                                continue;
                            }
                            else
                            {
                                if (conjugateVoxel.isWrite)
                                {
                                    VoxelChunk conjugateVoxelChunkSurfaceUpdateDatas;
                                    if (tempVoxelChunks.TryGetValue(conjugateKey, out conjugateVoxelChunkSurfaceUpdateDatas))
                                    {

                                    }
                                    else
                                    {
                                        conjugateVoxelChunkSurfaceUpdateDatas = tempVoxelChunks[conjugateKey] = mainDictionaryVoxelChunks[conjugateKey];
                                    }
                                    conjugateVoxel.surfaces[conjugateVoxel3DIndexs[directionIndex]] = true;
                                    conjugateVoxelChunkSurfaceUpdateDatas.SurfaceUpdateDatas.addIndexs[conjugateVoxel3DIndexs[directionIndex]]
                                        .Add(conjugateVoxel.chunkIndex);
                                    allAddTempShadows.Add(new TempShadow(conjugateVoxel, conjugateVoxelChunk, conjugateVoxel3DIndexs[directionIndex]));

                                }
                            }
                        }
                        else
                        {
                            removeIndex[directionIndex].Add(voxel3D.chunkIndex);
                        }
                    }
                    else
                    {
                        //做非边境处理
                        if (voxel3D.surfaces[directionIndex])
                        {
                            removeIndex[directionIndex].Add(voxel3D.chunkIndex);

                            allRemoveTempShadows.Add(new TempShadow(voxel3D, voxelChunk, directionIndex));
                            //SetBlockShadowRemove(voxel3D, voxelChunk, directionIndex, tempVoxelChunks);
                        }
                        else
                        {
                            Voxel3D conjugateVoxel3D = voxelChunk.mainVoxels[voxel3D.GetChunkIndexNoBorder(directionIndex)];
                            if (conjugateVoxel3D == null)
                            {

                            }
                            else
                            {
                                if (conjugateVoxel3D.isWrite)
                                {
                                    if (conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] == false)
                                    {
                                        conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] = true;
                                        addIndex[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel3D.chunkIndex);

                                        allAddTempShadows.Add(new TempShadow(conjugateVoxel3D, voxelChunk, VoxelMetadata3D.ConjugateDirectionIndexs[directionIndex]));
                                    }
                                }
                            }
                        }
                    }

                }//for end


            }
            else
            {
                for (int directionIndex = 0; directionIndex < VoxelCategories.SURFACE_LENGTH; directionIndex++)
                {
                    if (voxel3D.surfaces[directionIndex])
                    {
                        removeIndex[directionIndex].Add(voxel3D.chunkIndex);

                        allRemoveTempShadows.Add(new TempShadow(voxel3D, voxelChunk, directionIndex));
                        //SetBlockShadowRemove(voxel3D, voxelChunk, directionIndex, tempVoxelChunks);
                    }
                    else
                    {
                        Voxel3D conjugateVoxel3D = voxelChunk.mainVoxels[voxel3D.GetChunkIndexNoBorder(directionIndex)];
                        if (conjugateVoxel3D == null)
                        {
                        }
                        else
                        {
                            if (conjugateVoxel3D.isWrite)
                            {
                                if (conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] == false)
                                {
                                    conjugateVoxel3D.surfaces[conjugateVoxel3DIndexs[directionIndex]] = true;
                                    addIndex[conjugateVoxel3DIndexs[directionIndex]].Add(conjugateVoxel3D.chunkIndex);


                                    //conjugateVoxel3D.colorShadow[conjugateVoxel3DIndexs[directionIndex]][0] = 0;
                                    //conjugateVoxel3D.colorShadow[conjugateVoxel3DIndexs[directionIndex]][1] = 0;
                                    //conjugateVoxel3D.colorShadow[conjugateVoxel3DIndexs[directionIndex]][2] = 0;
                                    //conjugateVoxel3D.colorShadow[conjugateVoxel3DIndexs[directionIndex]][3] = 0;

                                    allAddTempShadows.Add(new TempShadow(conjugateVoxel3D, voxelChunk, conjugateVoxel3DIndexs[directionIndex]));
                                    //SetBlockShadowAdd(conjugateVoxel3D, voxelChunk,
                                    //    conjugateVoxel3DIndexs[directionIndex], tempVoxelChunks, false);
                                }
                            }
                        }
                    }
                }
            }
         //   */

            voxelChunk.mainVoxels[voxel3D.chunkIndex] = null;
        }

        /*
        private void SetBlockShadowRemove(Voxel3D voxel3D, VoxelChunk voxelChunk, int direction)
        {
            if (voxel3D.IsBorder)
            {
                Vector3Int[] edgeVector3Ints = new Vector3Int[VoxelCategories.UNIT_VERTICES_LENGTH];
                switch (direction)
                {
                    case 0:
                        edgeVector3Ints[0] = voxel3D.worldPosition + new Vector3Int(1, 1, 0);
                        edgeVector3Ints[1] = voxel3D.worldPosition + new Vector3Int(1, -1, 0);
                        edgeVector3Ints[2] = voxel3D.worldPosition + new Vector3Int(1, 0, -1);
                        edgeVector3Ints[3] = voxel3D.worldPosition + new Vector3Int(1, 0, 1);
                        break;
                    case 1:
                        edgeVector3Ints[0] = voxel3D.worldPosition + new Vector3Int(-1, 1, 0);
                        edgeVector3Ints[1] = voxel3D.worldPosition + new Vector3Int(-1, -1, 0);
                        edgeVector3Ints[2] = voxel3D.worldPosition + new Vector3Int(-1, 0, 1);
                        edgeVector3Ints[3] = voxel3D.worldPosition + new Vector3Int(-1, 0, -1);
                        break;
                    case 2:
                        edgeVector3Ints[0] = voxel3D.worldPosition + new Vector3Int(0, 1, 1);
                        edgeVector3Ints[1] = voxel3D.worldPosition + new Vector3Int(0, 1, -1);
                        edgeVector3Ints[2] = voxel3D.worldPosition + new Vector3Int(-1, 1, 0);
                        edgeVector3Ints[3] = voxel3D.worldPosition + new Vector3Int(1, 1, 0);
                        break;
                    case 3:
                        edgeVector3Ints[0] = voxel3D.worldPosition + new Vector3Int(0, -1, -1);
                        edgeVector3Ints[1] = voxel3D.worldPosition + new Vector3Int(0, -1, 1);
                        edgeVector3Ints[2] = voxel3D.worldPosition + new Vector3Int(-1, -1, 0);
                        edgeVector3Ints[3] = voxel3D.worldPosition + new Vector3Int(1, -1, 0);
                        break;
                    case 4:
                        edgeVector3Ints[0] = voxel3D.worldPosition + new Vector3Int(0, 1, 1);
                        edgeVector3Ints[1] = voxel3D.worldPosition + new Vector3Int(0, -1, 1);
                        edgeVector3Ints[2] = voxel3D.worldPosition + new Vector3Int(1, 0, 1);
                        edgeVector3Ints[3] = voxel3D.worldPosition + new Vector3Int(-1, 0, 1);
                        break;
                    case 5:
                        edgeVector3Ints[0] = voxel3D.worldPosition + new Vector3Int(0, 1, -1);
                        edgeVector3Ints[1] = voxel3D.worldPosition + new Vector3Int(0, -1, -1);
                        edgeVector3Ints[2] = voxel3D.worldPosition + new Vector3Int(-1, 0, -1);
                        edgeVector3Ints[3] = voxel3D.worldPosition + new Vector3Int(1, 0, -1);
                        break;
                }

                for (int edgeIndex = 0; edgeIndex < VoxelCategories.UNIT_VERTICES_LENGTH; edgeIndex++)
                {
                    Voxel3D edgeConjugate;
                    if (allVoxels.TryGetValue(edgeVector3Ints[edgeIndex], out edgeConjugate))
                    {
                        voxel3D.SetColorShadowRemove(direction, edgeIndex, edgeConjugate);
                    }
                }
            }
            else
            {
                int[] edgeIndexs = voxel3D.GetChunkEdgeIndexNoBorder(direction);
                for (int edgeIndex = 0; edgeIndex < VoxelCategories.UNIT_VERTICES_LENGTH; edgeIndex++)
                {
                    Voxel3D edgeConjugate = voxelChunk.mainVoxels[edgeIndexs[edgeIndex]];
                    if (edgeConjugate == null)
                    {

                    }
                    else
                    {
                        voxel3D.SetColorShadowRemove(direction, edgeIndex, edgeConjugate);
                    }
                }
            }
        }
        */


        /*
        private void SetBlockShadow(Voxel3D voxel3D,
             Dictionary<int, VoxelChunk> dictionaryVoxelChunks)
        {
            VoxelChunk voxelChunk = dictionaryVoxelChunks[voxel3D.chunkPosition.GetHashCode()];
            if (voxel3D.IsBorder)
            {
                int directionIndex = 0;


                int[] edgeBlockIndexs = new int[4];
                int[] edgeChunkIndexs = new int[4];

                if (voxel3D.m_Array_Surface[VoxelMetadata3D.DIRECTION_UP_2D])
                {
                    int[] edgeBlockNoBorderIndexs = voxel3D.GetChunkEdgeIndexNoBorder(directionIndex);
                    //上
                    if (voxel3D.specificBorders[VoxelMetadata3D.DIRECTION_UP])
                    {
                        edgeChunkIndexs[VoxelMetadata3D.DIRECTION_UP_2D] =
                            Vector3IntHashCodeChange(voxelChunk.GetHashCode(), VoxelMetadata3D.DIRECTION_UP, 1);

                        edgeBlockIndexs[VoxelMetadata3D.DIRECTION_UP_2D] =
                            Voxel3D.GetChunkIndexBorderChunkConjugate(edgeBlockNoBorderIndexs[VoxelMetadata3D.DIRECTION_UP_2D], VoxelMetadata3D.DIRECTION_UP);
                    }
                    else
                    {
                        edgeBlockIndexs[VoxelMetadata3D.DIRECTION_UP_2D] = edgeBlockNoBorderIndexs[VoxelMetadata3D.DIRECTION_UP_2D];
                        edgeChunkIndexs[VoxelMetadata3D.DIRECTION_UP_2D] = voxelChunk.GetHashCode();

                        //下
                        if (voxel3D.specificBorders[VoxelMetadata3D.DIRECTION_DOWN])
                        {
                            edgeChunkIndexs[VoxelMetadata3D.DIRECTION_DOWN_2D] =
                                Vector3IntHashCodeChange(voxelChunk.GetHashCode(), VoxelMetadata3D.DIRECTION_DOWN, 1);

                            edgeBlockIndexs[VoxelMetadata3D.DIRECTION_DOWN_2D] =
                                Voxel3D.GetChunkIndexBorderChunkConjugate(edgeBlockNoBorderIndexs[VoxelMetadata3D.DIRECTION_DOWN_2D], VoxelMetadata3D.DIRECTION_DOWN);
                        }
                        else
                        {
                            edgeBlockIndexs[VoxelMetadata3D.DIRECTION_DOWN_2D] = edgeBlockNoBorderIndexs[VoxelMetadata3D.DIRECTION_DOWN_2D];
                        }
                    }
                }



            }
            else
            {

                for (int i = 0; i < 6; i++)
                {
                    if (voxel3D.m_Array_Surface[i])
                    {
                        //
                        int[] edgeIndexs = voxel3D.GetChunkEdgeIndexNoBorder(i);
                        for (int edgeIndex = 0; edgeIndex < 4; edgeIndex++)
                        {
                            Voxel3D edgeConjugate = voxelChunk.mainVoxels[edgeIndexs[edgeIndex]];
                            if (edgeConjugate == null)
                            {

                            }
                            else
                            {
                                voxel3D.SetColorShadowAdd(i, edgeIndex, edgeConjugate);
                            }
                        }
                        //
                    }
                }
            }
        }
        */
        

        /// <summary>
        /// 往一个方向走value个长度然后获得那个chunk的hashCode
        /// </summary>
        /// <param name="hashCode"></param>
        /// <param name="direction"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static int Vector3IntHashCodeChange(int hashCode, int direction, int value)
        {
            int returnHashCode;
            switch (direction)
            {
                case 0:
                    returnHashCode = hashCode + value;
                    break;
                case 1:
                    returnHashCode = hashCode - value;
                    break;
                case 2:
                    returnHashCode = hashCode + (value << 0x0A);
                    break;
                case 3:
                    returnHashCode = hashCode - (value << 0x0A);
                    break;
                case 4:
                    returnHashCode = hashCode + (value << 0x14);
                    break;
                case 5:
                    returnHashCode = hashCode - (value << 0x14);
                    break;
                default:
                    returnHashCode = hashCode;
                    break;
            }
            return returnHashCode;
        }

        /// <summary>
        /// 往一个方向的反方向走value个长度然后获得那个chunk的hashCode
        /// </summary>
        /// <param name="hashCode"></param>
        /// <param name="direction"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static int Vector3IntHashCodeNegativeChange(int hashCode, int direction, int value)
        {
            int returnHashCode;
            switch (direction)
            {
                case 0:
                    returnHashCode = hashCode - value;
                    break;
                case 1:
                    returnHashCode = hashCode + value;
                    break;
                case 2:
                    returnHashCode = hashCode - (value << 0x0A);
                    break;
                case 3:
                    returnHashCode = hashCode + (value << 0x0A);
                    break;
                case 4:
                    returnHashCode = hashCode - (value << 0x14);
                    break;
                case 5:
                    returnHashCode = hashCode + (value << 0x14);
                    break;
                default:
                    returnHashCode = hashCode;
                    break;
            }
            return returnHashCode;
        }
    }





}
